package com.sanq.product.cab.interceptors;

import com.google.common.collect.Maps;
import com.sanq.product.cab.annotations.IgnoreSecurity;
import com.sanq.product.cab.annotations.IgnoreTokenSecurity;
import com.sanq.product.cab.redis.constants.BusCode;
import com.sanq.product.cab.enums.SecurityFieldEnum;
import com.sanq.product.cab.exceptions.BusException;
import com.sanq.product.cab.tools.web.GlobalUtil;
import com.sanq.product.cab.tools.web.ParamUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * version: 基础控制器
 * ---------------------
 *
 * @author sanq.Yan
 * @date 2020/1/26
 */
public abstract class BaseInterceptor implements HandlerInterceptor {

    protected Map<String, Object> objectMap;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
            response.setStatus(HttpStatus.OK.value());
            return false;
        }

        if (handler instanceof HandlerMethod) {

            //验证ip是否在黑名单中
            String ip = GlobalUtil.getBrowserIp(request);

            if (checkIp(request, ip)) {
                throw new BusException(String.format("ip:%s，访问被限制， 加入黑名单", ip), BusCode.IP_CODE);
            }

            HandlerMethod hm = (HandlerMethod) handler;
            IgnoreSecurity ignoreSecurity = hm.getMethodAnnotation(IgnoreSecurity.class);

            if (ignoreSecurity != null) {
                return true;
            }

            // 先获取参数
            objectMap = getParamMap(request);

            if (objectMap == null || objectMap.isEmpty())
                throw new BusException("缺少必要参数", BusCode.PARAM_CODE);

            //是否忽略token验证
            IgnoreTokenSecurity s = hm.getMethodAnnotation(IgnoreTokenSecurity.class);

            if (s == null) {
                Object o = objectMap.get(SecurityFieldEnum.TOKEN.getName());
                if (o == null)
                    throw new BusException(String.format("参数%s不存在", SecurityFieldEnum.TOKEN.getName()), BusCode.PARAM_CODE);

                if (!checkToken(request, (String) o))
                    throw new BusException(String.format("%s已过期，请重新登录", SecurityFieldEnum.TOKEN.getName()), BusCode.TOKEN_CODE);
            }
            return true;
        }
        throw new Exception("访问被限制");
    }


    protected Map<String, Object> getParamMap(HttpServletRequest request) {

        switch (request.getMethod()) {
            case "GET":
                return ParamUtils.getInstance().getParam2Get(request);
            case "POST":
            case "PUT":
            case "DELETE":
                return ParamUtils.getInstance().json2Map(ParamUtils.getInstance().get());
        }

        return Maps.newHashMap();
    }

    protected abstract boolean checkToken(HttpServletRequest request, String token);

    protected abstract boolean checkIp(HttpServletRequest request, String ip);
}
